home *** CD-ROM | disk | FTP | other *** search
- // File "INIT Dispatcher.c" - Sample source that shows one way to make FAT INIT resources.
- // Original source by Matt Slot (fprefect@umich.edu) - 7/3/95
- // Changes from 1.1 to 1.2 - 1/20/96
- // * Fixed the Gestalt call to to gracefully accept an error code on 68K
- // systems that simply doesn't know about the new selector.
- // Changes from 1.2 to 1.3 - 4/20/96
- // * Updated for CW8
- // * Removed test for PPC 620
- // * Better ResError checking
-
-
- #include <A4Stuff.h>
- #include <CodeFragments.h>
- #include <Gestalt.h>
- #include <MixedMode.h>
-
- //#define ____DEBUG____
- #define k68KProcType '68K•'
- #define kPPCProcType 'PPC•'
-
- // * ******************************************************************************* *
- // * ******************************************************************************* *
-
- typedef pascal void (*INITProcPtr)(void);
- enum {
- uppINITProcInfo = kPascalStackBased
- };
- #define CallINITProc(proc) (* ((INITProcPtr) proc))()
-
- // * ******************************************************************************* *
- // * ******************************************************************************* *
- // Function Prototypes
-
- void __Startup__(void);
- void main(void);
-
- // * ******************************************************************************* *
- // * ******************************************************************************* *
- // Incredibly Important! - This file must be the first in the segment, and this
- // function must be the first one in it... defining the custom resource header.
- // Here, we can use high level language to call our *real* main.
-
- void __Startup__() {
- main();
- }
-
- // * ******************************************************************************* *
- // * ******************************************************************************* *
-
- void main() {
- long saveA4 = SetCurrentA4();
- Boolean isNative;
- short procID;
- long response;
- Handle procHandle;
- Str255 textBuff, errBuff;
-
- // Determine the environment and prepare our code
- if (Gestalt(gestaltSystemVersion, &response) || (response < 0x0604)) goto END;
-
- // Of course, certain 68K machines don't know this selector,
- // so just wimp out if Gestalt returns an error.
- if (Gestalt(gestaltNativeCPUtype, &response)) isNative = FALSE;
- else switch(response) {
- /* Various 68k CPUs... */
- case gestaltCPU68000: // 0x0001
- case gestaltCPU68010: // 0x0002
- case gestaltCPU68020: // 0x0003
- case gestaltCPU68030: // 0x0004
- case gestaltCPU68040: // 0x0005
- isNative = FALSE;
- break;
- /* PPC 601 */
- case gestaltCPU601: // 0x0101
- case gestaltCPU603: // 0x0103
- case gestaltCPU604: // 0x0104
- isNative = TRUE;
- break;
- /* Anything Else... */
- default:
- isNative = FALSE;
- break;
- }
-
- // Get information about *this* resource, because we want to load the
- // PPC or the 68K resource with the same ID for consistency.
- procHandle = RecoverHandle((Ptr) __Startup__);
- if (!procHandle || ResError()) goto END;
-
- GetResInfo(procHandle, &procID, (ResType *) &response, textBuff);
- if (ResError()) goto END;
-
- #ifdef ____DEBUG____
- DebugStr("\pINIT Dispatcher... kewl!");
- #endif ____DEBUG____
- if (isNative && (procHandle = Get1Resource(kPPCProcType, procID))) {
- RoutineDescriptor rd = BUILD_ROUTINE_DESCRIPTOR(uppINITProcInfo, 0);
- RoutineDescriptorPtr rdPtr = &rd;
- ConnectionID cfmConnID;
- ProcPtr procPtr = 0;
-
- // Prepare for execution by finding or building a routine descriptor
- HLockHi(procHandle);
- if (**(short **) procHandle == _MixedModeMagic) procPtr = (ProcPtr) *procHandle;
- else if (! GetMemFragment(*procHandle, GetHandleSize(procHandle),
- textBuff, kLoadNewCopy, &cfmConnID, (Ptr *) &procPtr, errBuff)) {
-
- // The way MixedMode.h is structured, the current ISA gets set to 68k
- // We need override this for our upcoming procedure... so override it.
- rd.routineRecords[0].ISA = ((ISAType) kPowerPCISA) | ((RTAType) kPowerPCRTA);
- rd.routineRecords[0].procDescriptor = procPtr;
- }
-
- if (procPtr) {
- SetA4(saveA4);
- CallINITProc(rdPtr);
- saveA4 = SetCurrentA4();
-
- // Normally we would close the CFM Connection... but we want it to
- // live if the rsrc Handle was detached and is still hanging around.
- if (procHandle == Get1Resource(kPPCProcType, procID)) CloseConnection(&cfmConnID);
-
- // Skip over the 68k boring stuff... we're done!
- goto END;
- }
-
- // Something went wrong w/ PPC resource... we'll clean up and try 68K
- HUnlock(procHandle);
- ReleaseResource(procHandle);
- }
-
- // If we don't run the PPC code (either by intention or error), then
- // we can alway fall back on friendly 68K code... and it's easy too!
- if (procHandle = Get1Resource(k68KProcType, procID)) {
- HLockHi(procHandle);
- SetA4(saveA4);
- CallINITProc(*procHandle);
- saveA4 = SetCurrentA4();
- }
-
- END:
- SetA4(saveA4);
- }
-
-